#include <buola/gui.h>

#include <buola/gui/cicon.h>
#include <buola/gui/cmenu.h>
#include <buola/gui/caccelerator.h>
#include <buola/gui/cwindow.h>

namespace buola { namespace gui {

CMenuItem::CMenuItem(EType pType,PMenu pSubMenu,const std::wstring &pText,PIcon pIcon,const std::wstring &pComment)
    :   mType(pType)
    ,   mText(pText)
    ,   mComment(pComment)
    ,   mIcon(pIcon)
    ,   mGroup(nullptr)
    ,   mFlags(FLAG_NONE)
{
    if(!pSubMenu)
        pSubMenu=new CMenu;

    mSubMenu=pSubMenu;
}

CMenuItem::CMenuItem(EType pType,const PWindow &pWindow)
    :   mType(pType)
    ,   mGroup(nullptr)
    ,   mWindow(pWindow)
    ,   mFlags(FLAG_NONE)
{
    
}

CMenuItem::CMenuItem(EType pType,const std::wstring &pText,PIcon pIcon,CAccelerator *pAccelerator,const std::wstring &pComment)
    :   mType(pType)
    ,   mText(pText)
    ,   mComment(pComment)
    ,   mIcon(pIcon)
    ,   mGroup(nullptr)
    ,   mFlags(FLAG_NONE)
{
    if(pAccelerator)
    {
        pAccelerator->eTriggered.Connect(&CMenuItem::Trigger,this);
        mAccelText=pAccelerator->GetKeyName();
    }
}

CMenuItem::~CMenuItem()
{
    if(mGroup)
    {
        mGroup->mItems.erase(this);
        if(mGroup->mItems.empty())
            delete mGroup;
    }
}

void CMenuItem::SetCheckable(bool pCheckable)
{
    if(pCheckable==GetFlag(FLAG_CHECKABLE)) return;

    if(pCheckable)
        SetFlag(FLAG_CHECKABLE);
    else
        UnsetFlag(FLAG_CHECKABLE);

    OnChange();
}

void CMenuItem::SetDefault(bool pDefault)
{
    if(pDefault==GetFlag(FLAG_DEFAULT)) return;
    
    if(pDefault)
        SetFlag(FLAG_DEFAULT);
    else
        UnsetFlag(FLAG_DEFAULT);

    OnChange();
}

void CMenuItem::SetHidden(bool pHidden)
{
    if(pHidden==GetFlag(FLAG_HIDDEN)) return;
    
    if(pHidden)
        SetFlag(FLAG_HIDDEN);
    else
        UnsetFlag(FLAG_HIDDEN);
    
    OnChange();
}

void CMenuItem::SetDisabled(bool pDisabled)
{
    if(pDisabled==GetFlag(FLAG_DISABLED)) return;
    
    if(pDisabled)
        SetFlag(FLAG_DISABLED);
    else
        UnsetFlag(FLAG_DISABLED);
    
    OnChange();
}

void CMenuItem::GroupWith(PMenuItem pOther)
{
    if(!mGroup)
    {
        if(pOther->mGroup)
        {
            mGroup=pOther->mGroup;
            mGroup->mItems.insert(this);
            return;
        }
        
        mGroup=new SGroup;
        mGroup->mItems.insert(this);
    }

    if(pOther->mGroup) //both have a group, merge them
    {
        SGroup *lGroup=pOther->mGroup;
        for(std::set<CMenuItem*>::iterator i=lGroup->mItems.begin();i!=lGroup->mItems.end();++i)
        {
            mGroup->mItems.insert(*i);
            (*i)->mGroup=mGroup;
        }

        delete lGroup;
    }

    mGroup->mItems.insert(pOther.get());
    pOther->mGroup=mGroup;
}

void CMenuItem::Trigger()
{
    if(IsCheckable())
        Check(true);
    else
        eTriggered();
}

void CMenuItem::Check(bool pChecked)
{
    if(!GetFlag(FLAG_CHECKABLE)) return;
    if(pChecked==GetFlag(FLAG_CHECKED)) return;

    if(pChecked)
    {
        SetFlag(FLAG_CHECKED);
        eTriggered();

        if(mGroup)
        {
            for(std::set<CMenuItem*>::iterator i=mGroup->mItems.begin();i!=mGroup->mItems.end();++i)
            {
                if(*i!=this)
                    (*i)->Check(false);
            }
        }
    }
    else
    {
        UnsetFlag(FLAG_CHECKED);
    }

    OnChange();
}

void CMenuItem::AddMenu(CMenu *pMenu)
{
    mMenus.insert(pMenu);
}

void CMenuItem::RemoveMenu(CMenu *pMenu)
{
    mMenus.erase(pMenu);
}

void CMenuItem::OnChange()
{
    for(std::set<CMenu*>::iterator i=mMenus.begin();i!=mMenus.end();++i)
        (*i)->OnItemChanged();
}

/*namespace gui*/ } /*namespace buola*/ }
